import { create } from 'zustand'
import { persist, type StorageValue } from 'zustand/middleware'

type MonacoEditor = typeof import('monaco-editor')

export interface CodeSorterData {
  id: number,
  code: string
}

interface CodeState {
  monaco: MonacoEditor | null
  restored: Boolean
  editorCode: string
  sorter: CodeSorterData[]

  initMonaco: (monaco: MonacoEditor) => Promise<void>
  updateEditorCode: () => void

  setSorter: (data: CodeSorterData[]) => void
  onEditorChange: (code: string) => void
}

const DefaultCode = `\
add r0 r2 r0
sub r1 r2 r0`

function CodeToSorter(code: string) {
  return code.split('\n').map((v, i) => ({
    id: i + 1, // line number
    code: v,
  } as CodeSorterData)).filter(v => !!v.code)
}

const PersistName = "si"

function Serilize(data: CodeState) {
  const e = {
    editorCode: data.editorCode
  }
  console.log('[save]', PersistName, 'with', e)
  localStorage.setItem(PersistName, JSON.stringify(e))
}

function Deserilize() {
  const str = localStorage.getItem(PersistName);
  if (!str) return null;
  const state = JSON.parse(str);
  console.log('[restore]', PersistName, 'result', state)
  return state as CodeState
}

const useCodeStore = create<CodeState>(
  (set, get) => ({
    monaco: null,
    restored: false,
    editorCode: '',
    sorter: [],

    async initMonaco(monaco) {
      console.log('get monaco instance', monaco)
      console.log('[get]', (get()))

      const session = Deserilize()
      const code = session?.editorCode.replaceAll('\r\n', '\n') ?? DefaultCode

      monaco.editor.getModels().forEach(v => {
        v.setEOL(monaco.editor.EndOfLineSequence.LF)
      })
      monaco.editor.getEditors()[0].setValue(code)

      set({
        monaco,
        restored: true,
        editorCode: code,
        sorter: CodeToSorter(code),
      })
    },

    updateEditorCode() {
      const { monaco, editorCode } = get();
      if (monaco) {
        monaco.editor.getEditors()[0].setValue(editorCode)
      }
    },

    setSorter(data) {
      set({ sorter: data })
    },

    onEditorChange(code) {
      set({
        editorCode: code,
        sorter: CodeToSorter(code),
      })

      const store = get();
      if (store.restored) {
        Serilize(store)
      }
    },

  })
)

export default useCodeStore
